package com.zxq.factory;

import com.zxq.factory.annotate.DecoderField;
import com.zxq.factory.annotate.BigLittleEndianMark;
import com.zxq.factory.datatrim.CurIndex;
import com.zxq.factory.datatrim.DataTrimFactory;
import com.zxq.factory.datatrim.ITrimInterpreter;
import com.zxq.factory.decoder.FiledDecoderFactory;
import com.zxq.factory.decoder.IFieldDecoder;
import com.zxq.factory.enums.EField;
import com.zxq.factory.enums.ETrimMethod;
import com.zxq.factory.utils.BigLittleEndian;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.xmlbeans.impl.util.HexBin;

import java.lang.reflect.Field;
import java.util.*;


public class DecoderFactory {

    /**
     * 按顺序将字段解析
     * @param model 实体对象
     * @param data 数据内容
     * @return 返回值
     */
    @SneakyThrows
    public static Object decodeObj(Object model, byte[] data)  {
        List<Field> fields = sequenceField(model.getClass());
        CurIndex curIndex = new CurIndex();
        //解析字段包含的参数
        for (Field field : fields) {
            DecoderField decoderField = field.getAnnotation(DecoderField.class);
            Integer param = decoderField.param();
            ETrimMethod eTrimMethod = decoderField.method();
            ITrimInterpreter iTrimInterpreter = DataTrimFactory.instance().create(eTrimMethod);
            byte[] dstBuff = iTrimInterpreter.interpreter(data, curIndex, param);
            BigLittleEndianMark bigLittleEndianMark = field.getAnnotation(BigLittleEndianMark.class);
            if(bigLittleEndianMark != null) {
                String serialStr = bigLittleEndianMark.serial();
                dstBuff = BigLittleEndian.decoder(serialStr,dstBuff);
            }

            field.setAccessible(true);
            if(decoderField.field() != EField.Frame) {
                //类型解析
                EField eFieldType = decoderField.field();
                IFieldDecoder iFieldDecoder = FiledDecoderFactory.instance().create(eFieldType);
                Object fieldObject = iFieldDecoder.decoder(dstBuff);
                field.set(model, fieldObject);
            }
            if(decoderField.field() == EField.Frame) {
                Object value = field.get(model);
                if(value != null) {
                    decodeObj(value, dstBuff);
                    System.out.println(String.format("frame:%s value:%s", HexBin.bytesToString(dstBuff), value));
                }
            }
        }

        return model;
    }

    private static List<Field> sequenceField(Class cla) {

        Map<Integer, Field> fieldHash = new TreeMap<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;
            }
        });
        do {
            Field[] fields = cla.getDeclaredFields();
            //获取所有的功能字段
            for (Field field : fields) {
                if (field.isAnnotationPresent(DecoderField.class)) {
                    DecoderField encoderField = field.getAnnotation(DecoderField.class);
                    Integer sequence = encoderField.sequence();
                    fieldHash.put(sequence,field);
                }
            }
        } while ((cla = cla.getSuperclass()) != null);
        List<Field> fieldList = new ArrayList<>();
        for(Map.Entry<Integer,Field> item: fieldHash.entrySet()) {
            fieldList.add(item.getValue());
        }
        return fieldList;

    }




}
